/*
 * This file is part of the openHiTLS project.
 *
 * openHiTLS is licensed under the Mulan PSL v2.
 * You can use this software according to the terms and conditions of the Mulan PSL v2.
 * You may obtain a copy of Mulan PSL v2 at:
 *
 *     http://license.coscl.org.cn/MulanPSL2
 *
 * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
 * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
 * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
 * See the Mulan PSL v2 for more details.
 */
#include "hitls_build.h"
#if defined(HITLS_CRYPTO_CMVP_ISO19790) || defined(HITLS_CRYPTO_CMVP_FIPS)
#include <string.h>
#include "crypt_cmvp_selftest.h"
#include "cmvp_common.h"
#include "err.h"
#include "crypt_errno.h"
#include "crypt_eal_pkey.h"
#include "crypt_eal_rand.h"
#include "bsl_err_internal.h"
#include "crypt_utils.h"
#include "crypt_util_rand.h"
#include "crypt_algid.h"
#include "securec.h"
#include "bsl_sal.h"

#define BITS_OF_BYTE 8

typedef struct {
    const char *rnd;
    const char *sk;
    const char *pk;
    const char *msg;
    const char *sig;
    int32_t algId;
    int32_t type;
} CMVP_MldsaVector;

static const CMVP_MldsaVector MLDSA_VECTOR[] = {
    {
        // https://github.com/usnistgov/ACVP-Server/tree/master/gen-val/json-files/ML-DSA-sigGen-FIPS204
        .rnd = "1D073BE3C59909102F6C26537E61E56CDB37FE1167E092DC3B73067E1B43B2A2",
        .sk = "C5459B7F833D8862B24945270793A9FA036D1C1CFB9AF2048FD6A53A5194ADB1FC6055E75441771C6E34EDF641C5B92DC33D5987ED44059728D873D6A3156BE51F5DCFBBADE70683E03D0605F365199AAF9A045564760FCDE95BF7C65868606D281BBF74E23A8739B39E2E34E0C3B6C254C3B6D3FC26F3F5D3A618070E7A54439B2845E4280593A22C88C42842C65009A369023806441621982262430065A1B8484194909BC06193164182A0848B9401114466C1468E6004801A45712433861A4605C14291D28841C2B22C53A0419842854B844159449150C610521861E088115C484252C869020330C9006484162901C1289930280880255C480AA3A6919B188460089104884D0949309CC26540122810470C0446494BA2901B028402472900B044190842DBC841A0A66583C46D93046950461023B88800157089064C2288110218891CC8454C30728AC20DC80049144205084230E2865123002062140DCCB08083A86C11239283A80488C291A0068A2024115B0828D1C4215380702384648394904B229122C5700A1592E08085184865E3206A4112300A268C0B354E14944404401010260280B801CA4650C1C80420C20180122290A420D31244C3863113047209978CA1C64113B12DDC362642289183B46810170CD922904B104C63068294866CD31285091240C1209199124CD8464043B88184103202098EDC28291C405023C99118056C62B031CBA2688B286112450610248E04444151101114178CC004112230214C802C8AB4904C28119038264BC46409264C1015500416491A8708942406C4A220011792E030702033295194515AB08589120624C304088165D43470C8404A203252A0948C9B142112476564B88962321284388C11891091144193982CE300729990500AA4606080044B346C01070648A48144000EA4364D03142C1817720A190013868414841040800102A22CD23232C4C41018C93149C02162B064DB002D04A421C190694A384C1385211A2988A0228E8CC4314A044C92907091B8680B29259930200CB7651A238A0241420B158CA484249B420114C585A304922228220A0389DC269192128C840601D036302404288BB88409112EC9121223120954284410090224965001878492B45040B649A486290C9610A41269132648A0366E9080690B02489C2049C4384918280D0429651A4964E23649C08485D0845160460C8CB04C1A9690E1340EC9220513494A51A845180168C4A0898812024CC0883324F1662FFA6CA7BDA4C113CCBD9B4D696EBA9A7F1B12DCCAD143D2FB35669A47E89432B51B4AACC086720CAD29D5AAF2A9290F5D3E4980B92BB6B82A0C07D46791FE0931CDDAF181DE924F4430DC0E02E901C73A0E4FD6539529DC7E4F98D8AEDCF68E3D1EFC0411A55EC05464C64F098199F1EF0846800DB2B7B4F116137237D12C214FA0B9C344ACAC5B684F76C7962CA1097DBE39F01ADEA74228A14D67B2FD891F41A010EB34CCA36A4AFE1F7A7BF23FC6CDD333161ABB3317D23E4863580883572647F80739748A6DCF4677CDAB621B0085F3C5A965A1BAA2881E9966651DFC6F9EF23BF08F0E7A9291A924B2BEBEA44D3ED6D9A5442A3897457C4A24C52DDE62CF03A413BA4F1CFFF5D7AD6F118C3749414D1ACDEEAFB14793F1609CE885B9856E10076F18A6106430610797802E1617AB1F066520A5487AB980AA928382EC2831A1FC873D9630BD21336540CC6AD23BE49BD18515A8568993C9B4525C42290AD4607E17DAAE37BAC65B82CF3524B22B3F7A2DAD9B42AA7E45EC27857F92C3288DF7734C4A1C8B2CB6990DF2D8EA92BF75F9E68797742240F5322FA26F0069675CA96F0DA7983960E71E74F285CE7FCEAB33F9FBBF52636771E537AB608EAC188F0112A6E579AAC2E519440D89FD43D313E4EAE4432E89587FCCFC487AB43B33F66F0885B7CCEDB2BD65EA23A4EA0ED266A3B506268DFA363DD792CF358FAC0BD80F77271F73FC3057ADA74FF4BDFABAC429D29846E3F1F2C64FF79B3FDC2D1B36684ADE97D5465494DE92B7657B58FD8F51731F30447A54C0309607798A4213735B61453D77B3C38F76182253172BCF1076D974D25F1A006A743DB61B4B34375E04A54FAF059A7F95FE3E7569A5BDCCBE09C1E31B17F92C47D1A5254B3BA346F0FDB42D2DC70B377D4E1347ACB30556C9BD24CAB617143503F1316C58B3A6B19B39342BCA9A0F9BA7D0A835216603F43212865A97DA9F495E59F273BCCED6E0A3BE990A6D5E13769F1AC4FC1FDE3F6865CE3B554679DF2C59121DC3F6CF1EB538AC0CC1EB66AAB155007D8B5369AFBAC0108B1F2F7B922C87E7C4D3E47B689F8A43F8CA8D7FC8A4C5BC037F6CCF6F3C878CFCA557ABE13019AC989155C7F5B73C045C1EB2C117BD3FFD7EA606B78DFFF56491BB9BD27499D00A539CBD5466F421D4BD27C8E669803E75297519EE509C1B52FDADBE141727FC55ECA7ACA14A52E9956F06F738FB9BC806D7EFA5BFF974AFF0F75CCE5F5FE7C998F883C8BEF882F8885D5243ACF262AF6CE9BFE1CEB390DB3C2DB268BEE42143B8FE8613EAE0A0D8E2AA8C137E46A9AA9C89371998A668CE58308720917B955BABA608177AAA17233412A1782D86BD12488A026B7F9FD44AE385C521B20144646319730B7699BAF8BF7246587EC2E33A7E5FD4E0A220C619B0A7B52527EC54C7BA7C40060C18C82EAA6F27CBFF30FB5DD7C9F4A2077078C16AD3DB0216AA965D250F7195B0BF338323E7EBCA4E18D1C4F80AD6FE81E38B256262D6E29885137205C148B15DFBEDEFCC4B58EF8EA017F5704F3E822DF785C4A33898F78A9F6D07FE1A02807500A646984A1EB1DA480D7AF4607F316E9459CB57EBA7F5E829F9EAE74C1A4A1AB1C9A0C9569208F5549B64391A7D9829715EA1E4A325C552A100D38DCC105EA11BF9B0BD8709D6EA67592D1DBAA4E2A541E0B6A1667CCD3610BFE73E477DA88050B0F037FE2F74B23D2342DDD2ABABF358748FA191255ACF82E863AC2234BC4549EA38E780FB65153CD83C2837B982FAC27B775DBD67953077DD4A219707A2BBAE8E2949FA74E1E41E44AF82E30471E656BD20358C96275ABAF7B547B52AA57FAB9245B6BD1CBDC5036BC53D75E3A09DAC5F16C4B321DD943B61954BFFB346ECD222E904D478D22D3BF886B680DA368FE5F74930B7B76B3FAB5EBA3FCE1A95F344D218AD8CC5236EB5F497799C2C99942007868CE8AC366477744BC5C1621569512EDCAACC1C9E282DA11098511A4191D8796D033F395E460E0E6213C7908077E71DCD8E2906A3D8C6583566077732DA25C8115B7260E1E2E936247622648CE8E0634852349CEBDF495C729434317633786399B18499CA013DA06FAB275EBEB8F78A58ED8F65B72E5E2E212D4D63595E0108976E8792C18A046A058B986E29BAC259D921E4743F4CF53BF3FF9FFD7B928F19EFB44F4657A8E93B1FAC23C0CF64A1630478D11C313F0CAEEE51787D30AEE34531E4C6A90D62C34EB7D5FE31C451C12879C97636F65C4AE47D05AC8109DA2589D5402402A5B09EDA9B3BA07723E38CBB4B5ED847601F348CE4B3A8D11916E617389160E98C997255D4CAB8DC",
        .pk = "C5459B7F833D8862B24945270793A9FA036D1C1CFB9AF2048FD6A53A5194ADB1B691D76050141493236DF39767EC9E2CDBAAF50613C38541E39F77E1415FF9BA5AD22EEDCFA2C69514ACC1FB9C8A3BD2D55E20E7624256E06A589D1C38EA2641723E9FA8A45A546050A266073F6977B5801DF8C4CF2DCD6965BD032C5D07269AD534CDD25495E574800E36733EAB8CB473163608097C271F8A75E9C4CBCE5170EA05CF4FD41288C4A57A6FB6685CC9B05FAEE90E674053270A8D700EE4313705DF5C14DA0A8D05CFD3807F3137C2F272D2A2DC18E7EC8A8E155E52A3974F413ACA3C3914C552CBD4CC36CD3F71FE8DEE522CD65FE4BFF2B51CE01DBAE4890D8B298995D159F60289277F77E9A8EA9DC1793E92730F4CA3514A9E2D0094123863F050393AF9932954A7AB58872EE333E522D87CDCF560C39DA2FF5750E0D85A6A81BCA8D42C6F3A08BA4A6D9B76385059030B1A131FDFF04F749D5AF87433FC05E6D9D580C832FF75F409BF9022EEAF8168A8B2ACCCA33BBC5FE1BDB44268EE77A39475439DADEFE6368CA1D1578EDCB5D3E5B862FAE157ED07584D1BDFADB71E31344FE51CF65A1D21D9037E876CC887FC30498CA6A54ADF7A4BCE24AE42C4C56AC29691A332108DBD00C4C368653B109D998C4B05BCDEB7C86E9CAEE0D1D55F2EE46ACAEA41AF1BFF43A479D9C928DEFDF99B009CE3B08AE4CA9CADAA407138B82F80766D9E648440D012404056B187DF2B19D5C263B0767C7A1FAB17D0E94F2FB342A9D3C98F6BA4D5EBE75264ADFDC4F167B9DA5D36FA3FD419007D0BC8CD1DBB7E3E897D9D03F6D2F674B3E4C7370ABCA10D91C7FCB13866866E254D991AAE86E917C78EFFADB02E88CD73F5CF47D54C18171828FDE585FBA2608B803D2623F466F3802A46201C67EACB811B139CAA240873D3E28CC7A9E71E3B3E3CCE1B98BD31E8DB83E72F7ECC2E4F4D93004DE855E6AD89E9A0C72279B67EF351E944CBA0BACC6FE31778209B13D9ED4D2AACFD054BB50BD8E379CF86678399991B31B3C179AADAC600DEA359787CB0A16F5EE911E5653E8E0CCF75FFEC9B1240928E1AD95F9630639AA20A529D27A5ACCCDA87FB2ECE63D42D50FBE70C69140CF3E6623E185EAEB219DEB1B6F0BBDC45587B46F7908B07E363A8EFDB4C0FE7881628A7F885054E43A1854DBFFD574A92C7318F1467441F554644BEC8F2C4F090678C0CF79B7CAC3800BAD6AC459FD8A87C2E410762DB26EC6C202CA996F3DF1B718B8E2C3DCDF90F61F9B97C9998B0E13B84D15D6C2ECA3BBBDF47E0CE53971A952B66915EA0FFA1D47B22F826FF51E1AD6E47C8FFAC640A8BCFD8B1E8E81A1D3AD4275552CDFE495464E32182E6FC707F41846325F6B53DCB2EAC2A5B3E5B84D6449681E9220642382FDE5F1479953E0C4DBB52B84258EB5E5847DFC527799BE27052BC19F3D769B48F8CDA7A3BB5414FC1232B66C8585F6AA2DD15978F1D0CDA59D03E13D8DBA6EBE1BD7E05D7AB0E429A156425E99DD8CC548C1B855810D3CBE0F599DC2FDFCF50C19FEBBCD6C2CD3BB98315C3016FAECC27FF0C7FE41F369511EC69BAAAFB1306B962A10A1A4BEDE822C86912A9453DAA30C7C1BD05038BE97E382651CB67C33B76CCFD33E1DBC3AE5149C485DFE2115779183DE801FEA99ECBBC069720D10E48C7437D9152030D48193898BAB2CCBCD363ED68FE5C74DA50D301CE7E4327BD387982C6A9C295F9EBD7F5764F009400F56BEDB8FAC01B3E4A33EB85AEA353906BB6B2CBC3EEA650EE428F40B969A193F99E7F2A40F71347066D16D29F33D364F8499F8EA96A1BA68E6CDB30F7909E889E4DB804A201B516EBB2",
        .msg = "73E28480E96EB5203E1E6DA81B3E433D07A4D5E1BDE100A7B97381EEEF61B73B736F55370B7457AFBFF669607C954C101DF1D8E4AB7D72C91A90F4401D7516A87FE93E684E602FE088805E30AA1A37AEB49F6306093625B1D7A4983B54DF301D26137BB44301B081F7E21AD02F4A6DB2CC48204E933DBCFA9D8169FEE227C2A3518D7B17CD03F7D4EDF644C530C33341A27A62178382ABA22B48B83AD59D783BA84B94628B102D2E60A3D03EE0E74255BC3F9C5A636BEEE5F00727FA325777BE3524AD7319F0803FD5C58272679BA95343EA924D5CAD6056BFAD520C4F03F4E31538D9893B85404E8CF908C3C1AE92421377FE273A8DF60FAEE8F9593E0C38DE894420FADEBDCA4112CCDA53BC0E3EB806911888E17E273533B84705C7521A664CC5D2006699D42CFFE0A561C22AC7F5EEC0AC597384A35B448694B2E9CA21B72E9D7D84042D78B3EA8B0D85D96BBCC76A30D0E90A4903C949D62DDE4DBEB70C657FCD7EF23225BEA9B7A2774EEC317165E271A1D78736FB1B6FB629EB216B8C035B720BDC21AADCD1A77041441F39FFFF1800B84BBA68D78AA9A09C0EF66619F8E69688EC3189669ABC5C3F5FC1A5BB0BC420513B637399E45F3C668744982DE6CF02E9DB45C4206A3C1CBE544C37C71027E0A7234CE9FBCF72CDB151F4A2B67BB08C9688B5E3EC6C449E255F430CB1118E5B2AFB14DE72668B9EBE31306409627B0260FE48566B51DCBB01BF4F876E31FFE2B6FD04327D118ADEDF2135C827465E75E7B23DB1F344582F2E91EFFD446ABFF3FA58AA67D763B49EAF3C9AC4810A4CF1BD94F22E25FA3A6065DC9631B0391A7AE5B6D374371B09D9E162AB2EA5BE0BC4C3A0365FE4A4AACDCCE283E13C95005A6A40828CCE1091F3F3D7D3CFC70742E9BDD2C7B09485BA6742A284C90FFCB0B4317336E8A7C9978B50CAE49F0CEC6F51AB93DDED4A32CDA1282955669BE2BED776DFBC3758EE7C9BC011E36226E390980820ACCED42794EDAB8ED62364579D342C0A829C8577715761B215DF20782FFF4CBABD3817EBE2F97C41AFCA46DE4DD5F103DB56E2DD53C559C3BAB720112F5A591D02B22D8E3807616479D83DCB1B1B6935F04FD3891C4F6CEAC74FF3445DF51AED9661FAB70BE153AEDFFF2CC0B02012ADFB7E064A48EF7FFC6A386F8BB64164A599EEEC2DC965B4F7991C799C4BD72336DAAA85C29BB3DC828FC31DBFD8EDCA599B7797D457ED588140A2FE24720FC087F84878819AFF1D30C2431B21E7F4999740EBAB0B5E1C7F532B20C1B9E49FC6AAE504B472850B444683F6F0D64084A1025BE2C338BAA58BADBAFE8CDE46A026B31A5BA588F7F57A032465B1EAC93951B8FF08590B52E1068B8DAB68FF0F68AC34E0B910923CA10AB5ED151AC131195923FD9C47F3D5076D2AEEE22902AB68193E26E203225C4F5446FB2F12BF0CF56DB7AD146728A6D316E4DC6DE291E706E400D526B69FD0063765C4EDC6EBEC4998D07411089068EF64DD81D42994B51934C21AFF09A4C5E2C8B6A4D0180AB098B8050197AB1BC8FFFFDECA7C8198BDDB36DDF87784A54E99681F2CD19068CE2E59026CE66FEBF72C399FA4573E2E01F5873438E6390A9B25EB7083A248019FA33608AA838E44106FC432811FCA3A0AEBC274D32F0B05370486FB2B805ABB5EBABE6E914819C36A5A6444EB710E212016F1DE5DA7BC5D12C851C347F89F75B3B0A39041EB51FBC91F1C908D1DCD88C8CDF3CAF50E6B024BFF5AE344E3E386EAF162B9FAD6EE14E1E6ECC9A9085D6CAB95A72B7E896615699E672F0032E2B6E8C598EB8A791E6FF872545C23D4A0B22F5A162699CC4C82DCEC321946E78636420F9D4ABA8DC7C2BC40F7CB0C43029CB7AD17866924C586105278523BDBAFF03D619F2571586046E17F4B5E535DD5553F6EF4F5D7C497E2350EA31AD4A941089F4A28E298410AABA3EE4B0007FA95B36D4CFB7CE34E3A654338667B0303352C7F5259E81143A13AEBD7441229DA1A9B8AA61E09D5C05AF83339263A7BF582E80074DB2296205A8C56D13D3D476E9E6973E27186EB36A15A75F0096CD0F70C28158C80C8448E7EFC2D0A3F771BD0E93DA5F632871E9774813D20B0151D88969548590E31AB445FA56A901E5FB7DE7A250526F4678D548223BD2C0CA433E88C4B6AF75596F5EF63995DC0DCA0BA31AE49C4E4FEAAD3018C9EF003200FDDBD664730D99165283F0904D0C7681AF37226DE3BEA62992FBD24FB5D7DD6FEF33361C5DAD012E10FE933267E2E67F8FCE91CC60214433F83401743BAA14F5B66873238C065040F3828F37E29E5DA4701DF9DACD93C86256C212BDFE04B0A03685C0C587569D79A96F603883AAF60AE20F78FC4A4B8B872E0A7A297FF9B063CB12D2E8994FB3E91A3416592AF66CD0EB92A7AE688BC3097E6A053B3FB7BDCFC88B3EF07BD1AD99ADD1881D54F9F13345B9D12DB978EEFA135ECA46D961BA92516B531C29B28ABCC061174785D66838A0DEACFA4A0F2B1B9758B3069E6DFAC5290DF3BD32A201E2A41B3CE4848652C65558A4D436E390452885BE3B953ED7FD55ABCDD8ACBD9155B2D3DDEA44539155944835665B5070F6D6A07AD3F7C4B681F5813815DBE71E9ACEF024A7DA76E59359A5F05BB0CD7E8DC1A9BFCB586045D77BB85139E6FB0B84A3F633C9EE3290966BC3344D9C223A56BB1F10E76BC29102CA02DA7B0D51568DF39C8DFB2429ACD2812B8DE9631FEA46236E8B3D88FF2121F167F38B0521C1F9AC975D86785DC5365C99D68CE4826ABD9DEF9CDF5AF3254122F658E960096C67B8726BCDDD8835B03DD630AE4044284A41539471998A7C18653B0EBE1E030C9D4826C10CDCBC1132613659C70B9A7C21B476EC6C96A48E898F3879EEBAA6E6979D4C38CC65DCB13DC02B262803FB40EF19C955049AA9D970E336E99DE9D15D975E6DC25C7995EB097B8716602571C068C663C0183E34F56FA8B26250E63CB4D69B5B99D4641752E9D18349900972334597CFCAAEB7F8E2E8323673CC8FCC9CC5172FE258B7583891127811112D37961C7EE22D72F1DC068DB4513CACA86551E2A466C79F8EA237B532CC8ABE7697397ED31C21D1AF312BEECF710AEF1D7B5D9D2697A856A66938A0C3DCA42DCAC5FEBF304A180602887A4CCD7E08B752FB81E6EA4574755679B8EB22246A298DE96CC8286DEAAF5247E2AB0D0EC06F445AD52DF62217278E171D2AF96A4DE533775B8DED4D0228298819017D028C7394B25560199DA0D9774A153A8604277B496FBD9972651199BAEECBA70B9E619351A32F10D58744E100CDE2FEE6CD16E52F149FEEA5EE26B3D33AF76E8EB1A76A48FC07ACE9568FD94E53779918E4C4B25D4A58A2F8AA9F595018776560933488670BE3BB8F643F87B79899454776DC4A9057F1B33A0E762CA7871128DE4761E798BF0FE53F651A4F0D92A17ED746E0613145BCD27ADD3766F1131099B33D1A6907708C27D80D904D3A7C907175674FC810C465E8B0795814D6E7F2CFA244CB9E0416D6270EF135973E6D4BC2F21E5EE3E2C2DE8EDB1E8FED979B190DA4CEAA764F829FC45B229AFF4331073056EFBFFFF5978E5CCB0B1093EB3159A9F078D8359D92B2A20E448B712FA999FBB27B1EE13509867D0448190224AE18E6A3BAA8DD3CB9AB65C0F5097C1482A4D40D4531F417FD54995604FF4908839717C09003C48DA740F46F36DE89A2EC81F3911185CBB5D976A78F26747DBE1A9CAF8EAC68968635F59310F7DD9E94D3BFDA72AD63A52315B429268A0A733A51EC4CC5736D52C704A0F4C6B8E179F2AD3189A9BECFAA576212EC0F2F9B373ABC4BF261C03BC65D59994257CB074601C348B1B1453F76545E1D0139CABC5046F8CFDDFEE33D4B6EF2CEE93513F864735CA6CB7FD22FFA8A3AE59F1BAAC92C42CE66403F7A92A88EC893E13FC9B139ED28AC02E6FF1EAD38FF58819BBC0402D40EA2E64DD59D1F5F9DBA8E8F68F9D2CC714B1FAD9D2AE5A4B415CC99F2464947235A39AC7DAB384849A011E4B3615ECBE273D1F55B263E485F53F91DD568FFAFAF41F0C7C5C53053407AD3DB7344F8BD33A1F2E1E5E8891411FF71BE0E78B31D7B8529BC1E826DE565C7DDE44A4037C111F78688866B34C8FE0F5A23AAA61B2E5F1E2BAB060AB4CA2A895D2AB187237C231C541997023B97303FC6C34C986EB2E29F6B6DCC6AED66112D8AB2026508C4C2A6CC1968FDBDBA7BE815E370C5E7B53B5F9FBA4BF612FF35BD1744BCA77F56133799345D9A127249B753DF5A13232872476971CB2C0C6BEB29B37B7FF761DFB7700693FE6A0C94D15AD64851FE18E938874C2E8736C629DB87AE6A3EF3CD1FFFA5CD630C5BBFCE75E0B88145D7E38983E26F4D17618584E302FFBE28828589DC1C2035779CDB97D",
        .sig = "CCD638E04CED882E7B1A9E2427F6029EAC98ECC9D5DB55F4812B4C416E770F5321A36F9429D39AE4122DEA3A1C3EDBE8F096AB23D48BD11D0D0B447BF7FD5D75F7561B6D21AE48154C7939AAB8C97BBEF789115CF20FF1CC6CEAEB7902CDB13D66DE16545BA190C2A71456341095C8B6F8118ADF196A63EFDB15609C085634EE9476F8086C89553D5D69EA9E7B592351CEE371DB250EBB8B547A909902C1C629836E58FAFF2996B0D32FC80381200483B1850983EA9FEA864ED24B42898E8C18F0B9AFDFBE48634CD3C8F33E6121CCEC08272F776F39E2AA3FA0BE1AED0D3B8F200B20E50F85284A649EC7563C1A919F092CD6BA519B0A38B85F6822B9A2B9378B63E4869BD745391928CA3812C846FEE057D27D79567F5CA36B4B3DEFCACB4E9356B78A2BAC246C4950804AA5F51CBF54F6C9E1043612B9C689B197D73F2F65BED76B69EF68D59B164FD0D374229C86433ABD3E9227C30BDF01E7B3072DEB1A45B7201C722DAC04D52F6A4045233266ADDA5B6883F0F270C1B1F4A5FFBF6517957E1DE46D1BE58532DF6EFF6C96B2205695ABEF9DD318AA81EE9224723C618BCED0C579812CEC6AE018E7E44F8A709AC01B136C5ECBE892701AF0FCD3A5ABD1AF15B10EBE19CF61087EC5FFE588412A25C44505D4B8C5E594FF0F77FFF2F5EFD7E36E7707BBE4FB335A00838BF693C05D23E979CE2379A11525254F2AE308CB7407BA2A4FBF073D1082262AF43B0D90C4B1CD3152502667C88A664BE6A71DA574F37095339916D3220A7F351D638403CDE9EF0085E714BC5F5E423E6D36E82BD2322FC2A02D8BE337F2A38BDA4BC8C196F208EB917B4573E2B167672ECFE0C354958F456D85A95E656DAA83785612945A91BA155D8996600C7210136F7F74CE5761C121024FE542C44898BCD79D5B22A232DE8EB4BF4AD03B3B1AEA83C1AA56E9F4558BA00A73B1EA61E7AE991D7453A67C5D06D822BD838ED7E0CEC504EF9CB42833A52DD426786BFD8E308A87CBDA7C15BD7A1022EDE96239EAB2B13BDF632788B67F712BCE3FD431DEF039D88A423E17EC4AECD774282C7257A6BC16E8838858F5FFF558B1870362D3DBA87F4D3142D7E8D2AF8A84AFF38A5C1BA928461C7A8D7C068F975A832383F4A82B0060ED3E74040B7E09479830DE26B3B45C59884F87E8E598C172DE7AF298E0952B4BA444B42F0B3C6140ECAC00429F4662FE577A22471A7CED89856205F8F0F2EEE8D33EFC945D4DFF37670C6B739C2031C864463B865FF2FB29A155B2735609254C4E1924D97514955049608A95282F0EF4B37DD15825B3FF66D6DF663571692A4548C13AE8512ECB4C807194A9870A638BD7FF59085AD867BAF5CC6198E32C3080E1514EBB12D6562AF3E6CACA8078633573FA4F0A713371672554EF5CE7C353CA27CD11B74E8E105EACF8FA92AF656083D9D18597846A799B857FF2923372CD4A15538319C12BCA83FFA5F658A5CFC48E5FF0ED1CD1E7A6E6D2876B4AAE80115469AB743304DAA324FD185B479DC5239D17E75A8BEA32277731B8164C033113728FBA5D01E95F72AF1C9CBAA3C666F0892894F3E4F14E2449DA8178250176C74634BA1405ABB0333D20E44F5CAA24C858C43099C3D402797F8B6081165AA8EA879B35907A4CDAFB9E478BF4C09581092958BAE72415305F0407E39F7D73FE6395763D0EE9639C7906E584833BBE4456218BCEF1F823E9D842EDC23DF77A11F2ADCE13A748AA1E0057A6DDC9B1497173BA48DAB5908609CD043FDDB44B397DF730606B2D7D27E221E6F1E7D4130EF4656D689FE24CF1F8EFAE96361426DAB83C24A9CCB081D5946B4F5D7E0089C7B39395C9B198A39E3D462290E90C657EB0B8702FBFF1CA4F3E27C960ED9F574F45C2497063D94617A06C0FBAFF55B195BE2A2D3CC32AED3A6FA081F8B58173EC5DA6E4E1128E09525CB3AF2BDCE75EA6FBEC31E3C4CA9274DFF3BA1528EC41ABC50C273C0398A46148DB495E802F955A60959053B174C5348C23EBFA0BE0F7CB7A8AB0C59B3CC90DBCE3D0A989DC64F152D2DA306ACE8203989DA7B73C53156E806D1F57B871CCD4A7FCFD3946EB9A8A73635E4F524AD323B517DFF38AD92C44D0F44FF2FE3B81CEB32A34E4E20A41ABB880D625EEEB6AA190AFAF06A5250CEC5D8B432D4B68E2BC2CE81E7D015A957465604CD4383686026777B0DE078E5F0E87D8DE00F46D7CF187EDF2A64095A3A377C4BA65A57FBC9EDEA140E79ABBCF294382A9C6BBAE4330186351BD810D1AED2D01FB0A816D31E284695D224C16AC5473F65607B135EAF79783394393C3C5865CA0CAD8DBF8FF2164FC69C03FE6DE178BDE02255BAB62E63ED672210D6761C3BA7B8625A567D548E85E6B6BD1DEC599A96E519CB99986AA927272F725953B555E9E5E04615DFC44FEFD3ADDC6D48B5145939A220F478468C706C6EA346BB3844A13DAC2F23B5F28A7ED60F5ED536BAE9FA7A07ABF811E4FD050C0831358B30B2EB64B7608076F620AA35867BFA8D7A463FF1C0563218A1A614FA1F2CD670F72AFAFCD687A79D85250DE77DBF7BB3FD38B44F118AD6FCB176FE50E01694C7C78C4D10A95621A99606F88DFE6E72E46326812AC6014D1091647219B51693F0FA23A2173446FACAA370FB0C967779295F8CD9BD2E3C1FB00242304EC21B6E1B0B15FB9A42761B1B63736A003FF2A8EDA22BD22640D2B327EA44F395098D4B64A878B26ED91472807772B7E639EF30741E7C824111DE5B0D3D0002B664849BCCBFB9985922929BBBEC0EDB7DF06F158E4A38BF91615F91935FCB54A60BF56D10012F18FDA39782221FA0646956D392E4174CFBA36E30658B58CAD707A52F26C6ACE72C05A8A6EEE5A4E2F69850361F8927D6A5B4084F85B9B4A225CF50BF048EB938E18FFB37631095DCB39C764BA40303A97EB33C9E63A2D1F6DF630DFC387FC1B10A524D7E638AFDF983BFFDCA14A3D24D5E2D807B27FF136D30C60FFBF2711D24FE10829657065500F5B8DFC2538AB434F030981ABAA6E4ABB10C0AB9D0BC9DB8B172AE93323237BB8521835EEB681A0DC2EE4E4A325404142014FE252C9821A5BEFC924892112116C21492C0F54074F4D615D54CD754E6AFF49D1D78EFE531E0C7FE7440FCF80752BE38EDBBE946586E94E89E76E7B7B6D032F69898B54BDC1B583338A0BCF60CE60ED407AA3C782FA677E92EA9D5565573D9CE551D10B6208480565E99FE0E72D997F4B96497346BCDFCABBDC494B968132DD632D111D24D230168D45FD8DDBEA851F80882AF700D809126A241618212D5052568E96989BB0C3C6CF202227363A3D6984B1B8C0F510172529474B57626E7B8391BDCDEC16282F3E3F545574757E85A7AEBFC4C9D00000000000000000000000000000000000000000000F1B2A3B",
        .algId = CRYPT_PKEY_ML_DSA,
        .type = CRYPT_MLDSA_TYPE_MLDSA_44,
    }
};

static const char *MLDSA_SEED_VECTOR = NULL;

static int32_t GetPkey(void *libCtx, const char *attrName, const CMVP_MldsaVector *vector, CRYPT_EAL_PkeyCtx **pkeyPrv,
    CRYPT_EAL_PkeyCtx **pkeyPub)
{
    int32_t ret = CRYPT_CMVP_ERR_ALGO_SELFTEST;
    CRYPT_EAL_PkeyPrv prvKey = { 0 };
    CRYPT_EAL_PkeyPub pubKey = { 0 };
    *pkeyPrv = CRYPT_EAL_ProviderPkeyNewCtx(libCtx, vector->algId, 0, attrName);
    GOTO_ERR_IF_TRUE(*pkeyPrv == NULL, CRYPT_CMVP_ERR_ALGO_SELFTEST);
    *pkeyPub = CRYPT_EAL_ProviderPkeyNewCtx(libCtx, vector->algId, 0, attrName);
    GOTO_ERR_IF_TRUE(*pkeyPub == NULL, CRYPT_CMVP_ERR_ALGO_SELFTEST);

    ret = CRYPT_EAL_PkeySetParaById(*pkeyPrv, vector->type);
    GOTO_ERR_IF_TRUE(ret != CRYPT_SUCCESS, ret);
    ret = CRYPT_EAL_PkeySetParaById(*pkeyPub, vector->type);
    GOTO_ERR_IF_TRUE(ret != CRYPT_SUCCESS, ret);

    int32_t val = 0;
    ret = CRYPT_EAL_PkeyCtrl(*pkeyPrv, CRYPT_CTRL_SET_MLDSA_ENCODE_FLAG, &val, sizeof(val));
    GOTO_ERR_IF_TRUE(ret != CRYPT_SUCCESS, ret);
    ret = CRYPT_EAL_PkeyCtrl(*pkeyPub, CRYPT_CTRL_SET_MLDSA_ENCODE_FLAG, &val, sizeof(val));
    GOTO_ERR_IF_TRUE(ret != CRYPT_SUCCESS, ret);

    prvKey.id = vector->algId;
    prvKey.key.mldsaPrv.data = CMVP_StringsToBins(vector->sk, &(prvKey.key.mldsaPrv.len));
    ret = CRYPT_EAL_PkeySetPrv(*pkeyPrv, &prvKey);
    GOTO_ERR_IF_TRUE(ret != CRYPT_SUCCESS, ret);

    pubKey.id = vector->algId;
    pubKey.key.mldsaPub.data = CMVP_StringsToBins(vector->pk, &(pubKey.key.mldsaPub.len));
    ret = CRYPT_EAL_PkeySetPub(*pkeyPub, &pubKey);
ERR:
    BSL_SAL_Free(prvKey.key.mldsaPrv.data);
    BSL_SAL_Free(pubKey.key.mldsaPub.data);
    return ret;
}

static int32_t TestVectorRandom(uint8_t *r, uint32_t rLen)
{
    uint8_t *rand = NULL;
    uint32_t randLen;

    rand = CMVP_StringsToBins(MLDSA_SEED_VECTOR, &randLen);
    if (rand == NULL) {
        return CRYPT_MEM_ALLOC_FAIL;
    }
    if (randLen < rLen) {
        BSL_SAL_Free(rand);
        return CRYPT_CMVP_ERR_ALGO_SELFTEST;
    }

    for (uint32_t i = 0; i < randLen; i++) {
        r[i] = rand[i];
    }
    BSL_SAL_Free(rand);
    return 0;
}

static bool TestMldsaSignVerify(void *libCtx, const char *attrName, const CMVP_MldsaVector *vector)
{
    bool ret = false;
    uint8_t *sign = NULL;
    uint8_t *signVec = NULL;
    uint32_t signLen;
    uint32_t signVecLen = 0;
    uint8_t *msg = NULL;
    uint32_t msgLen;
    CRYPT_EAL_PkeyCtx *pkeyPrv = NULL;
    CRYPT_EAL_PkeyCtx *pkeyPub = NULL;
    CRYPT_EAL_RandFunc func = CRYPT_RandRegistGet();
    CRYPT_EAL_RandFuncEx funcEx = CRYPT_RandRegistExGet();
    CRYPT_RandRegistEx(NULL);

    GOTO_ERR_IF_TRUE(
        GetPkey(libCtx, attrName, vector, &pkeyPrv, &pkeyPub) != CRYPT_SUCCESS, CRYPT_CMVP_ERR_ALGO_SELFTEST);
    signLen = CRYPT_EAL_PkeyGetSignLen(pkeyPrv);
    sign = BSL_SAL_Malloc(signLen);
    GOTO_ERR_IF_TRUE(sign == NULL, CRYPT_MEM_ALLOC_FAIL);

    msg = CMVP_StringsToBins(vector->msg, &msgLen);
    GOTO_ERR_IF_TRUE(msg == NULL, CRYPT_CMVP_COMMON_ERR);
    signVec = CMVP_StringsToBins(vector->sig, &signVecLen);
    GOTO_ERR_IF_TRUE(signVec == NULL, CRYPT_CMVP_COMMON_ERR);

    // regist rand function
    MLDSA_SEED_VECTOR = vector->rnd;
    CRYPT_RandRegist(TestVectorRandom);
    // sign
    GOTO_ERR_IF_TRUE(CRYPT_EAL_PkeySign(pkeyPrv, CRYPT_MD_MAX, msg, msgLen, sign, &signLen) != CRYPT_SUCCESS,
        CRYPT_CMVP_ERR_ALGO_SELFTEST);
    // compare the signature

    GOTO_ERR_IF_TRUE(signLen != signVecLen, CRYPT_CMVP_ERR_ALGO_SELFTEST);
    GOTO_ERR_IF_TRUE(memcmp(signVec, sign, signLen) != 0, CRYPT_CMVP_ERR_ALGO_SELFTEST);
    // verify
    GOTO_ERR_IF_TRUE(CRYPT_EAL_PkeyVerify(pkeyPub, CRYPT_MD_MAX, msg, msgLen, sign, signLen) != CRYPT_SUCCESS,
        CRYPT_CMVP_ERR_ALGO_SELFTEST);
    ret = true;
ERR:
    BSL_SAL_Free(sign);
    BSL_SAL_Free(signVec);
    BSL_SAL_Free(msg);
    CRYPT_EAL_PkeyFreeCtx(pkeyPrv);
    CRYPT_EAL_PkeyFreeCtx(pkeyPub);
    CRYPT_RandRegist(func);
    CRYPT_RandRegistEx(funcEx);
    return ret;
}

bool CRYPT_CMVP_SelftestMldsaSignVerify(void)
{
    bool ret = TestMldsaSignVerify(NULL, NULL, &MLDSA_VECTOR[0]);
    return ret;
}

bool CRYPT_CMVP_SelftestProviderMldsaSignVerify(void *libCtx, const char *attrName)
{
    return TestMldsaSignVerify(libCtx, attrName, &MLDSA_VECTOR[0]);
}

#endif /* HITLS_CRYPTO_CMVP_ISO19790 || HITLS_CRYPTO_CMVP_FIPS */